<template>
  <div class="container">
    <!-- 左侧资源树 -->
    <div class="sidebar" :style="{ width: sidebarWidth + 'px' }" @contextmenu.prevent>
      <div class="tree-header">服务器列表</div>
      <div class="tree-container">
        <el-tree
            :data="resourceTree"
            node-key="id"
            :props="treeProps"
            @node-click="handleNodeClick"
        >
          <template #default="{ node, data }">
            <span class="tree-node">
              <el-icon v-if="data.type === 'host'"><Monitor/></el-icon>
              <el-icon v-else><Folder/></el-icon>
              {{ node.label }}
            </span>
          </template>
        </el-tree>
      </div>
      <el-button class="fixed-button" type="warning" @click="fileManagement()">文件管理</el-button>
    </div>
    <!-- 拖动条 -->
    <div
        class="resize-handle"
        @mousedown="startResizing"
        :class="{ active: isResizing }"
    ></div>
    <!-- 右侧终端区域 -->
    <div class="main">
      <div class="terminal-tabs">
        <el-tabs
            ref="tabsRef"
            v-model="activeSession"
            type="card"
            closable
            @tab-remove="closeSession"
            @tab-change="handleTabChange"
        >

          <el-tab-pane
              v-for="session in sessions"
              :key="session.id"
              :label="session.name"
              :name="session.id"
          >
            <!-- SSH 终端显示 -->
            <div
                v-if="session.type === 'ssh'"
                :id="`terminal-${session.id}`"
                class="terminal-container"
            />

            <!-- RDP显示 -->
            <div v-if="session.type === 'rdp'" class="rdp-container">
              <div :id="`display-${session.id}`" class="guac-display"></div>
              <!-- 剪贴板输入区域 -->
              <textarea
                  v-if="session.type === 'rdp'"
                  :id="`clipboard-${session.id}`"
                  class="clipboard-input"
                  ref="clipboardInputs"
                  @input="handleClipboardInput(session)"
                  @paste="handleClipboardPaste($event, session)"
              ></textarea>
              <!-- 添加粘贴按钮 -->
              <div class="paste-button-container">
                <el-button
                    type="primary"
                    size="small"
                    @click="focusClipboardInput(session)"
                    class="paste-button"
                >
                  <el-icon>
                    <DocumentCopy/>
                  </el-icon>
                  粘贴内容
                </el-button>
              </div>
            </div>

          </el-tab-pane>
        </el-tabs>
        <div
            v-show="showContextMenu"
            class="custom-menu"
            :style="{ left: menuX + 'px', top: menuY + 'px' }"
            @click.stop>
          <div class="menu-item" @click="handleMenuClick(1)">
            <el-icon>
              <CopyDocument/>
            </el-icon>
            <span>&nbsp;复制窗口</span></div>
          <div class="menu-item" @click="handleMenuClick(2)">
            <el-icon>
              <Refresh/>
            </el-icon>
            <span>&nbsp;重新连接</span></div>
          <div class="menu-item" @click="handleMenuClick(3)">
            <el-icon>
              <CircleClose/>
            </el-icon>
            <span>&nbsp;关闭当前</span></div>
          <div class="menu-item" @click="handleMenuClick(4)">
            <el-icon>
              <CircleCloseFilled/>
            </el-icon>
            <span>&nbsp;关闭所有</span></div>
        </div>
      </div>
    </div>

    <!-- 连接对话框 -->
    <el-dialog v-model="connectDialogVisible" width="500" style="margin-top: 200px;" draggable>
      <template #header="{  titleId, titleClass }">
        <div class="my-header">
          <h4 :id="titleId" :class="titleClass">
            连接到服务器：{{ connectInfo.user }}@{{ connectInfo.label }}
          </h4>
        </div>
      </template>
      <div v-if="connectInfo.rdp_port" style="display: flex; align-items: center; justify-content: center; gap: 10%;">
        <el-button color="#333a3c" style="width: 45%" type="default" @click="connectStatus(2)">
          连接到SSH
        </el-button>
        <el-button color="#333a3c" style="width: 45%" type="default" @click="connectStatus(1)">
          连接到RDP
        </el-button>
      </div>
      <el-button color="#333a3c" style="width: 100%" type="default" @click="connectStatus(2)" v-else>
        连接到SSH
      </el-button>
    </el-dialog>

    <FileManagerMentDialog
        v-model="fileDialogVisible"
        :progressData="progressData"
        :sessionsData="sessions"
        :dialogVisible="fileDialogVisible"
        :currentSessionIDData="currentSessionID"
        :activeSessionData="activeSession"
        :connectInfo="connectInfo"
    />
  </div>
</template>

<script setup>
import {
  CircleClose,
  CircleCloseFilled,
  CopyDocument,
  DocumentCopy,
  Folder,
  Monitor,
  Refresh
} from '@element-plus/icons-vue'
import {ref, onMounted, onBeforeUnmount, onUnmounted, nextTick, watch} from 'vue'
import {Terminal} from 'xterm'
import {FitAddon} from 'xterm-addon-fit'
import {WebLinksAddon} from 'xterm-addon-web-links'
import 'xterm/css/xterm.css'
import {ElMessage} from 'element-plus'
import requestUtil from '@/utils/request'
import Sortable from 'sortablejs'
import FileManagerMentDialog from "@/views/mgr/terminal/components/fileManagerMentDialog.vue";
import router from "@/router"
import {useDark, useToggle} from '@vueuse/core'
import Cookies from "js-cookie";
import Guacamole from "guacamole-client";

useToggle(useDark())

const tabsRef = ref(null)
const currentSessionID = ref('')
const sidebarWidth = ref(280)
const isResizing = ref(false)
let startX = 0
let startWidth = 0
const fileDialogVisible = ref(false)
const progressData = ref(0)
const showContextMenu = ref(false)
const menuX = ref(0)
const menuY = ref(0)
const sessionID = ref('')
const connectType = ref('ssh')
const clipboardInputs = ref([])

// 资源树示例数据
const resourceTree = ref([])

const username = Cookies.get('username');
const activeKeyboard = ref(null)

// 请求剪贴板权限
const requestClipboardPermission = async () => {
  try {
    // 检查是否已有权限
    if (navigator.permissions) {
      const permissionStatus = await navigator.permissions.query({
        name: 'clipboard-read',
        allowWithoutGesture: false
      });

      if (permissionStatus.state === 'granted') {
        return true;
      }
    }

    // 直接尝试读取剪贴板 (会触发权限请求)
    try {
      await navigator.clipboard.readText();
      return true;
    } catch (readError) {
      console.log('直接读取剪贴板失败，需要用户手势:', readError);
    }

    return false;
  } catch (err) {
    console.error('剪贴板权限请求失败:', err);
    return false;
  }
};

// 聚焦剪贴板输入区域
const focusClipboardInput = (session) => {
  const clipboardId = `clipboard-${session.id}`;
  const clipboardInput = document.getElementById(clipboardId);

  if (clipboardInput) {
    clipboardInput.style.display = 'block';
    clipboardInput.focus();
    clipboardInput.select();

    // 添加临时样式使其可见（仅用于调试）
    clipboardInput.style.position = 'absolute';
    clipboardInput.style.top = '10px';
    clipboardInput.style.left = '10px';
    clipboardInput.style.width = '300px';
    clipboardInput.style.height = '100px';
    clipboardInput.style.zIndex = '10000';
    clipboardInput.style.opacity = '0.8';
    clipboardInput.style.background = '#2e3436';
    clipboardInput.style.color = '#ffffff';

    // 3秒后隐藏
    setTimeout(() => {
      clipboardInput.style.display = 'none';
    }, 3000);
  }
};

// 处理剪贴板粘贴 (RDP)
const handleClipboardPaste = async (event, session) => {
  event.preventDefault();
  event.stopPropagation();

  try {
    // 请求剪贴板权限
    const hasPermission = await requestClipboardPermission();

    if (!hasPermission) {
      ElMessage.warning('需要剪贴板权限才能粘贴内容');
      return;
    }

    let pasteText = '';

    // 尝试从系统剪贴板获取内容
    if (navigator.clipboard && navigator.clipboard.readText) {
      try {
        pasteText = await navigator.clipboard.readText();
      } catch (err) {
        console.error('读取剪贴板失败:', err);
        // 回退到从事件对象获取
        pasteText = event.clipboardData?.getData('text/plain') || '';
      }
    } else {
      // 兼容旧版浏览器
      pasteText = event.clipboardData?.getData('text/plain') || '';
    }

    if (pasteText && pasteText.trim() !== '') {
      // 发送到远程桌面
      sendClipboardToRemote(session, pasteText);

      // 更新文本区域内容（可选）
      const clipboardInput = document.getElementById(`clipboard-${session.id}`);
      if (clipboardInput) {
        clipboardInput.value = pasteText;
      }
    }
  } catch (error) {
    console.error('粘贴处理失败:', error);
    ElMessage.error('粘贴失败: ' + error.message);
  }
};

// 发送剪贴板内容到远程桌面
const sendClipboardToRemote = (session, text) => {
  if (!session.socket) {
    console.error('RDP连接未初始化');
    return;
  }

  try {
    const stream = session.socket.createClipboardStream('text/plain');
    const writer = new Guacamole.StringWriter(stream);
    writer.sendText(text);
    writer.sendEnd();
    console.log('已发送剪贴板内容到远程桌面:', text.length + '字符');
  } catch (error) {
    console.error('发送剪贴板内容失败:', error);
    ElMessage.error('发送剪贴板内容失败: ' + error.message);
  }
};

// 处理剪贴板输入 (RDP)
const handleClipboardInput = (session) => {
  const clipboardId = `clipboard-${session.id}`;
  const clipboardInput = document.getElementById(clipboardId);

  if (clipboardInput && session.socket) {
    const text = clipboardInput.value;

    if (text && text.trim() !== '') {
      sendClipboardToRemote(session, text);
    }

    // 清空输入框
    clipboardInput.value = '';
  }
};

// >>> 新增：全局 Ctrl+V 处理 <<<
const handleCtrlV = async (event) => {
  if (!event.ctrlKey || (event.key !== 'v' && event.key !== 'V')) return;

  // 找到当前激活的会话
  const session = sessions.value.find(s => s.id === activeSession.value);
  if (!session || session.type !== 'rdp') return;

  event.preventDefault();
  event.stopPropagation();

  try {
    // 请求剪贴板权限
    const hasPermission = await requestClipboardPermission();
    if (!hasPermission) {
      ElMessage.warning('需要剪贴板权限才能粘贴内容');
      return;
    }

    // 读取系统剪贴板
    const pasteText = await navigator.clipboard.readText();
    if (pasteText && pasteText.trim() !== '') {
      sendClipboardToRemote(session, pasteText);
    }
  } catch (error) {
    console.error('粘贴失败:', error);
    ElMessage.error('粘贴失败: ' + error.message);
  }
};

const initHostTreeList = async () => {
  try {
    const res = await requestUtil.get('host/group/list?status=1')
    const data = res.data
    if (data.code === 200) {
      resourceTree.value = data.msg
    } else {
      ElMessage.error(data.msg)
    }
  } catch (error) {
    console.error('Error fetching table data:', error)
    ElMessage.error('请求失败，请稍后再试')
  }
}

initHostTreeList()

// 终端会话管理
const sessions = ref([])
const activeSession = ref('')
const connectDialogVisible = ref(false)
const connectInfo = ref({})

// Xterm终端实例映射
const terminals = new Map()

// 树形配置
const treeProps = {
  label: 'label',
  children: 'children'
}

// 初始化终端
const initTerminal = (sessionId) => {
  const container = document.getElementById(`terminal-${sessionId}`)
  if (!container) {
    throw new Error(`找不到终端容器: terminal-${sessionId}`)
  }

  const terminal = new Terminal({
    convertEol: true,
    disableStdin: false,
    screenReaderMode: true,
    cursorBlink: true,
    fontSize: 14,
    scrollback: 1000,
    theme: {
      background: '#2e3436',
      foreground: '#d3d7cf',
      cursor: '#e8e8e8',
      selection: '#d3d7cf',
      black: '#171421',
      red: '#C01C28',
      green: '#26A269',
      yellow: '#A2734C',
      blue: '#12488B',
      magenta: '#A347BA',
      cyan: '#2AA1B3',
      white: '#D0CFCC',
    },
  });

  const fitAddon = new FitAddon()
  terminal.loadAddon(fitAddon)
  terminal.loadAddon(new WebLinksAddon())

  terminal.open(container)
  fitAddon.fit()

  // 修复粘贴问题：移除阻塞剪贴板访问的自定义处理
  // 监听键盘事件,ctrl+c复制,ctrl+v粘贴
  terminal.attachCustomKeyEventHandler((event) => {
    if (event.ctrlKey) {
      const selectedText = terminal.getSelection();
      // 处理复制
      if (event.key === 'c' && selectedText) {
        if (navigator.clipboard) { // 添加兼容性检查
          navigator.clipboard.writeText(selectedText)
              .then(() => console.log('Copied:', selectedText))
              .catch(err => console.error('Copy failed:', err))
        }
        return false; // 阻止默认行为
      }
    }
    return true; // 允许其他键盘事件
  });


  terminals.set(sessionId, {terminal, fitAddon})
}

// 处理节点点击
const handleNodeClick = (data) => {
  if (data.type === 'host') {
    connectInfo.value = data
    connectDialogVisible.value = true
  }
}

// 添加对 activeSession 的监听
watch(activeSession, (newVal) => {
  if (newVal && terminals.has(newVal)) {
    const {fitAddon} = terminals.get(newVal)
    setTimeout(() => fitAddon.fit(), 50)
  }
})

const connectStatus = async (sta) => {
  if (sta === 1) {
    connectType.value = 'rdp'
    await connectServer()
  } else {
    connectType.value = 'ssh'
    await connectServer()
  }
}

const connectServer = async (position) => {
  try {
    let localSessionID = `session-${Date.now()}`

    const session = {
      host: connectInfo.value,
      id: localSessionID,
      name: `${connectType.value === 'ssh' ? '[SSH]' : '[RDP]'} ${connectInfo.value.label}`,
      type: connectType.value,
      connected: false,
      socket: null
    }

    if (typeof position === 'number') {
      sessions.value.splice(position, 0, session)
    } else {
      sessions.value.push(session)
    }
    activeSession.value = localSessionID
    currentSessionID.value = localSessionID;

    await nextTick()

    if (connectType.value === 'ssh') {
      initTerminal(session.id)
      setupSSHConnection(session)
    } else if (connectType.value === 'rdp') {
      initializeGuacamole(session)
    }

    connectDialogVisible.value = false
  } catch (error) {
    ElMessage.error(`连接失败: ${error.message}`)
  }
}

// 初始化Guacamole RDP连接
const initializeGuacamole = (session) => {
  const displayId = `display-${session.id}`;
  const displayElement = document.getElementById(displayId);

  if (!displayElement) {
    console.error(`RDP显示容器未找到: ${displayId}`);
    return;
  }

  // 添加剪贴板输入区域
  const clipboardId = `clipboard-${session.id}`;
  const clipboardInput = document.getElementById(clipboardId);
  if (!clipboardInput) {
    console.error(`剪贴板输入区域未找到: ${clipboardId}`);
  }

  // 事件处理
  const handleMouseEnter = () => {
    displayElement.style.cursor = 'none';
  };
  const handleMouseLeave = () => {
    displayElement.style.cursor = 'default';
  };

  displayElement.addEventListener('mouseenter', handleMouseEnter);
  displayElement.addEventListener('mouseleave', handleMouseLeave);

  session.mouseEventHandlers = {
    enter: handleMouseEnter,
    leave: handleMouseLeave
  };

  // 获取DPI
  const dpiElement = document.createElement('div');
  dpiElement.id = 'dpi';
  dpiElement.style.height = '1in';
  dpiElement.style.width = '1in';
  dpiElement.style.position = 'absolute';
  dpiElement.style.left = '-100%';
  document.body.appendChild(dpiElement);
  const dpi = Math.max(96, parseInt(getComputedStyle(dpiElement).getPropertyValue('width')));
  document.body.removeChild(dpiElement);

  // 计算显示区域
  const displayWidth = document.body.clientWidth - sidebarWidth.value - 10;
  const displayHeight = document.body.clientHeight - 50;

  const uniqueSessionId = `${username}_${session.id}`;

  // 创建Guacamole客户端 - 启用剪贴板支持
  const tunnel = new Guacamole.WebSocketTunnel(
      `${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}${requestUtil.getServerUrl()}ws_rdp/${uniqueSessionId}/${session.host.id}`
  );

  session.socket = new Guacamole.Client(tunnel);

  // 连接参数
  const params = `${displayWidth},${displayHeight},${dpi}`;

  // 连接远程桌面
  session.socket.connect(params);

  // 设置剪贴板处理 (从远程到本地)
  session.socket.onclipboard = function (stream, mimetype) {
    // 只处理文本类型
    if (mimetype.indexOf('text') === -1) return;

    // 创建剪贴板读取器
    const reader = new Guacamole.StringReader(stream);

    // 接收剪贴板数据
    let data = '';
    reader.ontext = function (text) {
      data += text;
    };

    // 当剪贴板流结束时，将数据设置到剪贴板输入框
    reader.onend = function () {
      if (clipboardInput) {
        clipboardInput.value = data;

        // 选中所有文本以便复制
        clipboardInput.select();

        // 请求权限并复制到系统剪贴板
        requestClipboardPermission().then(() => {
          navigator.clipboard.writeText(data).catch(err => {
            console.log('写入剪贴板失败:', err);
          });
        }).catch(err => {
          console.log('剪贴板权限被拒绝:', err);
        });
      }
    };
  };

  // 事件处理
  displayElement.appendChild(session.socket.getDisplay().getElement());
  const mouse = new Guacamole.Mouse(displayElement);

  mouse.onmousedown = mouse.onmousemove = mouse.onmouseup = function (state) {
    session.socket.sendMouseState(state);
  };


  if (activeKeyboard.value) {
    activeKeyboard.value.onkeydown = () => {
    };
    activeKeyboard.value.onkeyup = () => {
    };
    // 移除事件监听
    activeKeyboard.value = null;
  }

  if (displayElement) {
    // 使 displayElement 可聚焦，以便捕获键盘事件
    displayElement.tabIndex = 0;
    displayElement.focus();

    // 创建键盘处理器，仅绑定到当前 displayElement，实现事件隔离
    activeKeyboard.value = new Guacamole.Keyboard(displayElement);
    activeKeyboard.value.onkeydown = (keysym) => session.socket && session.socket.sendKeyEvent(1, keysym);
    activeKeyboard.value.onkeyup = (keysym) => session.socket && session.socket.sendKeyEvent(0, keysym);

    // 点击时自动聚焦
    displayElement.addEventListener('click', () => {
      displayElement.focus();
    });
  }
};

// 设置 SSH 连接
const setupSSHConnection = (session) => {
  const domain = window.location.hostname;
  const port = window.location.port;
  const wsUrl = `${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${domain}:${port}${requestUtil.getServerUrl()}ws/terminal?host_id=${session.host.id}`;

  session.socket = new WebSocket(wsUrl)

  const resetTimeout = () => {
    if (session.timeoutTimer) clearTimeout(session.timeoutTimer)
    session.timeoutTimer = setTimeout(() => {
      const term = terminals.get(session.id).terminal
      term.writeln('\r\n\x1b[31m连接已超时（30分钟无操作），自动断开连接\x1b[0m')

      if (session.socket) {
        if (session.socket.readyState === WebSocket.OPEN) {
          session.socket.close()
        }
        session.socket = null
      }
    }, 30 * 60 * 1000)
  }

  session.socket.onopen = () => {
    const term = terminals.get(session.id).terminal;
    const {fitAddon} = terminals.get(session.id)
    nextTick(() => {
      fitAddon.fit()
      handleResize()
    })

    setTimeout(() => {
      session.socket.send(JSON.stringify({
        flag: 'init',
        data: '\n'
      }));
    }, 100);

    term.onData((data) => {
      resetTimeout()
      if (session.socket.readyState === WebSocket.OPEN) {
        session.socket.send(JSON.stringify({flag: 'entered_key', entered_key: data}));
      }
    });

    resetTimeout()
  };

  session.socket.onmessage = (e) => {
    resetTimeout()
    const term = terminals.get(session.id).terminal
    try {
      const message = JSON.parse(e.data)
      switch (message.type) {
        case 'stdout':
          term.write(message.data)
          break
        case 'auth_error':
          ElMessage.error(`认证失败: ${message.data}`)
          router.replace('/login');
          break
        case 'connection_error':
          ElMessage.error(`连接错误: ${message.data}`)
          closeSession(session.id)
          break
        case 'heartbeat':
          console.log(message.data)
          break
        case 'progress':
          progressData.value = message.data;
          break
      }
    } catch {
      term.write(e.data)
    }
  }

  session.socket.onclose = function (event) {
    const terminalInfo = terminals.get(session.id)
    if (!terminalInfo) return

    const customCode = event.code
    let message = `\r\n\x1b[31m连接已关闭: `

    const codeMap = {
      1000: '正常关闭',
      1006: '异常断开',
      1012: '后端重启',
      4001: '认证失败',
      4002: '权限不足'
    }
    const term = terminalInfo.terminal
    message += codeMap[customCode]
    message += '\x1b[0m'
    term.writeln(message)
  }

  session.heartbeatTimer = setInterval(() => {
    if (session.socket?.readyState === WebSocket.OPEN) {
      session.socket.send(JSON.stringify({
        code: 200,
        type: "heartbeat",
        data: "ping"
      }))
    }
  }, 30000)

  session.socket.onerror = (error) => {
    ElMessage.error(`WebSocket 错误: ${error.reason}`)
    console.log(`WebSocket 错误: ${error.reason}`)
  }
}

// 关闭会话
const closeSession = (sessionId, closeAll) => {
  if (closeAll === 1) {
    sessions.value.forEach(item => {
      if (item.type === 'ssh') {
        terminals.get(item.id)?.terminal.dispose()
        terminals.delete(item.id)
        item.socket?.close()
      }
      if (item.type === 'rdp') {
        item.socket?.disconnect();
        if (activeKeyboard.value) {
          activeKeyboard.value.onkeydown = () => {
          };
          activeKeyboard.value.onkeyup = () => {
          };
          // 移除事件监听
          activeKeyboard.value = null;
        }
      }
      clearInterval(item.heartbeatTimer)
    })
    sessions.value = []
    return;
  }

  const sessionIndex = sessions.value.findIndex(s => s.id === sessionId)
  if (sessionIndex === -1) return


  const session = sessions.value[sessionIndex]

  sessions.value.splice(sessionIndex, 1)

  if (session.type === 'ssh') {
    const terminalInfo = terminals.get(sessionId)
    if (terminalInfo) {
      terminalInfo.terminal.dispose()
      terminals.delete(sessionId)
    }
  } else if (session.type === 'rdp') {
    session.socket?.disconnect();
    if (activeKeyboard.value) {
      activeKeyboard.value.onkeydown = () => {
      };
      activeKeyboard.value.onkeyup = () => {
      };
      // 移除事件监听
      activeKeyboard.value = null;
    }
  }

  if (session.socket) {
    if (session.socket.readyState === WebSocket.OPEN) {
      session.socket.close()
    }
    session.socket = null
  }

  clearInterval(session.heartbeatTimer)

  if (session.timeoutTimer) {
    clearTimeout(session.timeoutTimer)
  }

  if (activeSession.value === sessionId) {
    if (sessions.value.length > 0) {
      const lastSession = sessions.value[sessions.value.length - 1]
      activeSession.value = lastSession.id
      nextTick(() => {
        if (lastSession.type === 'ssh') {
          const {fitAddon} = terminals.get(lastSession.id)
          fitAddon.fit()
        }
      })
    } else {
      activeSession.value = ''
    }
  }
}

// 窗口大小变化处理
const cols = ref(0)
const rows = ref(0)

const handleResize = () => {
  terminals.forEach((info, sessionId) => {
    const {terminal, fitAddon} = info
    try {
      if (!terminal.element) return
      fitAddon.fit()

      const session = sessions.value.find(s => s.id === sessionId)
      if (!session?.socket) return
      if (session.socket.readyState !== WebSocket.OPEN) return

      const dimensions = fitAddon.proposeDimensions()
      if (!dimensions) return

      const localCols = dimensions.cols
      const localRows = dimensions.rows

      if (Number.isFinite(localCols)) {
        cols.value = localCols
      }
      if (Number.isFinite(localRows)) {
        rows.value = localRows
      }

      session.socket.send(JSON.stringify({
        flag: 'resize',
        cols: cols.value,
        rows: rows.value
      }))
    } catch (e) {
      console.error('Resize error:', e)
    }
  })
}

const handleBeforeClose = (event) => {
  if (sessions.value.length !== 0) {
    event.preventDefault();
    event.returnValue = '';
  }
};

// 标签右键菜单设置
const setupTabContextMenu = () => {
  nextTick(() => {
    const tabItems = tabsRef.value?.$el?.querySelectorAll('.el-tabs__item')
    tabItems?.forEach(item => {
      item.removeEventListener('contextmenu', handleTabRightClick)
      item.addEventListener('contextmenu', handleTabRightClick)
    })
  })
}

const handleTabRightClick = (e) => {
  e.preventDefault()
  menuX.value = e.clientX
  menuY.value = e.clientY
  showContextMenu.value = true
  sessions.value.forEach(item => {
    if (e.target.id.includes(item.id)) {
      sessionID.value = item.id
      connectInfo.value = item.host
    }
  })
}

const handleTabClose = () => {
  showContextMenu.value = false
}

const handleMenuClick = (e) => {
  switch (e) {
    case 1:
      connectServer()
      break
    case 2: {
      const index = sessions.value.findIndex(item => item.id === sessionID.value)
      if (index === -1) return
      const session = sessions.value[index]
      connectType.value = session.type
      closeSession(sessionID.value)
      connectServer(index)
      break
    }
    case 3:
      closeSession(sessionID.value)
      break
    case 4:
      sessions.value.forEach(item => {
        closeSession(item.id, 1)
      })
      break
  }
  handleTabClose();
}

const fileManagement = async () => {
  if (!currentSessionID.value) {
    ElMessage.warning("请先选择主机")
    return
  }
  // if (connectInfo.value.server_type === 2) {
  //   return
  // }

  fileDialogVisible.value = true
}

const handleTabChange = (id) => {
  currentSessionID.value = id;
  const session = sessions.value.find(s => s.id === id);
  if (!session) return;
  connectInfo.value = session.host;
  // 切换前，销毁上一个 RDP Keyboard
  if (activeKeyboard.value) {
    activeKeyboard.value.onkeydown = () => {
    };
    activeKeyboard.value.onkeyup = () => {
    };
    activeKeyboard.value = null;
  }

  // 只为当前 RDP tab 创建新的键盘处理器，并绑定到对应 displayElement
  if (session.type === 'rdp') {
    nextTick(() => {
      const displayElement = document.getElementById(`display-${session.id}`);
      if (displayElement) {
        // 确保元素可聚焦
        displayElement.tabIndex = 0;

        // 强制聚焦到显示区域
        displayElement.focus();

        // 创建新的键盘处理器
        activeKeyboard.value = new Guacamole.Keyboard(displayElement);
        activeKeyboard.value.onkeydown = (keysym) => {
          if (session.socket) {
            session.socket.sendKeyEvent(1, keysym);
          }
        };
        activeKeyboard.value.onkeyup = (keysym) => {
          if (session.socket) {
            session.socket.sendKeyEvent(0, keysym);
          }
        };

        // 添加点击事件自动聚焦
        displayElement.addEventListener('click', () => {
          displayElement.focus();
        });
      }
    });
  }
};

// 左右拖动条功能
const startResizing = (e) => {
  isResizing.value = true
  startX = e.clientX
  startWidth = sidebarWidth.value
  document.addEventListener('mousemove', handleMouseMove)
  document.addEventListener('mouseup', handleMouseUp)
  document.body.style.userSelect = 'none'
}

const handleMouseMove = (e) => {
  if (!isResizing.value) return
  const dx = e.clientX - startX
  const newWidth = startWidth + dx
  sidebarWidth.value = Math.max(280, Math.min(500, newWidth))
}

const handleMouseUp = () => {
  isResizing.value = false
  document.removeEventListener('mousemove', handleMouseMove)
  document.removeEventListener('mouseup', handleMouseUp)
  document.body.style.userSelect = ''
}

// 初始化拖拽
const initSortable = () => {
  const el = tabsRef.value?.$el?.querySelector('.el-tabs__nav')
  if (el) {
    Sortable.create(el, {
      animation: 150,
      draggable: '.el-tabs__item',
      filter: '.is-disabled',
      onEnd: ({oldIndex, newIndex}) => {
        if (oldIndex === newIndex) return
        const newSessions = [...sessions.value]
        const [movedItem] = newSessions.splice(oldIndex, 1)
        newSessions.splice(newIndex, 0, movedItem)
        sessions.value = newSessions
      }
    })
  }
}

onMounted(() => {
  window.addEventListener('resize', handleResize);
  window.addEventListener('beforeunload', handleBeforeClose);
  nextTick(() => {
    initSortable()
  })

  const observer = new MutationObserver(() => {
    setupTabContextMenu()
  })

  if (tabsRef.value?.$el) {
    observer.observe(tabsRef.value.$el, {
      childList: true,
      subtree: true
    })
  }

  onBeforeUnmount(() => {
    observer.disconnect()
  })

  window.addEventListener('click', handleTabClose);
  document.addEventListener('keydown', handleCtrlV);
})

onBeforeUnmount(() => {
  sessions.value.forEach(session => {
    if (session.type === 'rdp') {
      const displayElement = document.getElementById(`display-${session.id}`);
      if (displayElement) {
        displayElement.removeEventListener('mouseenter', session.mouseEventHandlers.enter);
        displayElement.removeEventListener('mouseleave', session.mouseEventHandlers.leave);
      }
    }
  });

  window.removeEventListener('resize', handleResize)
  terminals.forEach(info => info.terminal.dispose())
  sessions.value.forEach(session => {
    if (session.socket?.readyState === WebSocket.OPEN) {
      session.socket.close()
    }
  })
  document.removeEventListener('keydown', handleCtrlV);
})

onUnmounted(() => {
  window.removeEventListener('beforeunload', handleBeforeClose);
  window.removeEventListener('click', handleTabClose);
});
</script>

<style scoped>
/* 新增剪贴板相关样式 */
.clipboard-input {
  position: absolute;
  top: -9999px;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
  z-index: -1;
}

.paste-button-container {
  position: absolute;
  bottom: 20px;
  right: 20px;
  z-index: 1001; /* 确保在显示层之上 */
}

.paste-button {
  background-color: rgba(51, 58, 60, 0.7);
  border: 1px solid #5294e2;
  color: #ffffff;
  transition: background-color 0.3s;
}

.paste-button:hover {
  background-color: rgba(82, 148, 226, 0.8);
}

.rdp-container {
  position: relative;
  width: 100%;
  background: #2e3436;
  height: calc(100vh - 40px);
  overflow: hidden;
  cursor: default;
}

.guac-display {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1000;
  cursor: none;
  outline: none; /* 移除聚焦时的轮廓线 */
}

/* 确保标签页内容可见 */
:deep(.el-tab-pane) {
  height: 100%;
  overflow: visible;
}

.custom-menu {
  position: fixed;
  background: #14191a;
  border: 1px solid #333a3c;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 #333a3c;
  z-index: 2000;
  padding: 15px 0;
  min-width: 140px;
  height: 140px;
}

.menu-item {
  display: flex;
  color: #ffffff;
  padding: 8px 20px 8px 20px;
  cursor: pointer;
  transition: background 0.3s;
}

.menu-item:hover {
  background: #555e5f;
}

.el-tabs__nav {
  user-select: none;
}

.sortable-ghost {
  opacity: 0.6;
  background: #f5f7fa;
}

.sortable-chosen {
  border: 2px dashed #409EFF !important;
}

:deep(.el-progress-bar__inner) {
  transition: width 0.3s ease;
}

:deep(.el-dialog) {
  border-radius: 8px;
}

.el-overlay {
  color: #e3e3e3;
  bottom: 0;
  height: 100%;
  left: 0;
  overflow: auto;
  position: fixed;
  right: 0;
  top: 0;
  z-index: 2000;
}

.container {
  display: flex;
  height: 100vh;
  position: relative;
  background: #2e3436;

  .fixed-button {
    width: 240px;
    position: fixed;
    bottom: 20px;
    left: 20px;
    padding: 10px 20px;
    background-color: #2e3436;
    color: white;
    border: none;
    border-radius: 0;
    cursor: pointer;
    font-size: 18px;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
    font-family: 'Arial', sans-serif;
  }

  .fixed-button:hover {
    background-color: #555e5f;
  }

  .fixed-button:active {
    background-color: #2e3436;
  }

  .el-tabs {
    background-color: #14191a;
  }

  :deep(.el-tabs--card > .el-tabs__header .el-tabs__item.is-active) {
    background-color: lightgray;
    color: #14191a;
  }

  :deep(.el-tabs__item) {
    align-items: center;
    box-sizing: border-box;
    color: white;
    display: flex;
    font-size: var(--el-font-size-base);
    font-weight: 500;
    height: var(--el-tabs-header-height);
    justify-content: center;
    list-style: none;
    padding: 0 20px;
    position: relative;
  }

  :deep(.el-tabs--card > .el-tabs__header) {
    border-bottom: 0;
    align-items: center;
    display: flex;
    justify-content: space-between;
    margin: 0 !important;
    padding: 0;
    position: relative;

    .el-tabs__nav {
      border: 0 !important;
      border-bottom: none !important;
      border-radius: 4px 4px 0 0;
      box-sizing: border-box;
    }
  }
}

.sidebar {
  color: #fff;
  background-color: #14191a;
  height: 100vh;
  position: relative;
  z-index: 1;
  transition: width 0.2s;
}

.tree-header {
  padding: 15px;
  font-weight: bold;
  border-bottom: 0;
}

.tree-container {
  padding: 10px;
}

:deep(.el-tree) {
  --el-tree-node-content-height: 26px;
  --el-tree-node-hover-bg-color: #2e3436;
  --el-tree-text-color: var(--el-text-color-regular);
  --el-tree-expand-icon-color: var(--el-text-color-placeholder);
  background: #14191a;
  color: white;
  cursor: default;
  font-size: var(--el-font-size-base);
  position: relative;
}

.resize-handle {
  position: relative;
  width: 5px;
  background-color: #3d4447;
  cursor: col-resize;
  transition: background-color 0.2s;
  z-index: 100;
}

.resize-handle:hover,
.resize-handle.active {
  background-color: #5294e2;
}

.resize-handle::before {
  content: '';
  position: absolute;
  left: 1px;
  width: 3px;
  height: 100%;
  background-color: rgba(255, 255, 255, 0.1);
}

.resize-handle:hover::before,
.resize-handle.active::before {
  background-color: rgba(255, 255, 255, 0.3);
}

.main {
  overflow: hidden;
  flex: 1;
  background: #2e3436;
}

.el-main {
  overflow: hidden;
  padding: 20px;
}

.terminal-tabs {
  overflow: hidden;
  height: 100%;
}

.terminal-container {
  height: calc(100vh - 40px) !important;
  padding: 5px 0 0 5px;
  background: #2e3436;
  box-sizing: border-box;
  overflow: hidden;
}

.tree-node {
  display: flex;
  align-items: center;
  gap: 8px;
}

.el-icon {
  font-size: 16px;
}

/* 隐藏原本的粘贴按钮 */
.paste-button-container {
  display: none !important;
}
</style>